import os
import json
import socket
import threading
import subprocess


class Graz(object):
    def __init__(self, stimulator, config_data):
        self.preload_duration = -1
        self.wait_duration = 0
        self.stimulator = stimulator
        self.threadStim = threading.Thread(target=self.stimulator.start)
        # self.parentDir = os.path.abspath(os.path.dirname(os.getcwd()))
        self.parentDir = os.path.abspath(os.getcwd())
        cue_path_set = config_data.cuePathSet[config_data.affectedSide]
        self.FirstCuePathA = 'video:file://' + self.parentDir + ''.join(cue_path_set[0])
        self.FirstCuePathB = 'video:file://' + self.parentDir + ''.join(cue_path_set[1])
        self.SecondCuePath = 'image:file://' + self.parentDir + r'\cue_material\rest_img.png'
        self.moveSound = 'audio:file://' + self.parentDir + r'\cue_material\move_sound.wav'
        self.relaxSound = 'audio:file://' + self.parentDir + r'\cue_material\relax_sound.wav'
        self.stopSound = 'audio:file://' + self.parentDir + r'\cue_material\stop_sound.wav'
        self.onStimulatorActions = {}
        self.sock = socket.socket()

    def preload(self, is_online):
        self.onStimulatorActions = {
            'OVTK_GDF_Left': (self.FirstCuePathA, self.moveSound, is_online),
            'OVTK_GDF_class5': (self.FirstCuePathB, None, is_online),
            'OVTK_GDF_Right': (self.SecondCuePath, self.relaxSound, False),
            'OVTK_GDF_Start_Of_Trial': (None, None, False),
            'OVTK_GDF_End_Of_Trial': (None, self.stopSound, False),
            'OVTK_StimulationId_ExperimentStart': ("text:开始", None, False),
            'OVTK_StimulationId_ExperimentStop': ("text:结束", None, False),
        }
        self.sock.bind(("127.0.0.1", 4567))
        self.sock.listen(1)
        subprocess.Popen(
            self.parentDir + '\\controller\\release\\SharpBCI.exe ' +
            self.parentDir + '\\controller\\release\\config\\mi.sessionconfig')
        self.conn, _ = self.sock.accept()

        self.send_preload(self.FirstCuePathA, None)
        self.send_preload(self.FirstCuePathB, None)
        self.send_preload(self.SecondCuePath, None)
        self.send_preload(None, self.moveSound)
        self.send_preload(None, self.relaxSound)
        self.send_preload(None, self.stopSound)

    def start_stim(self, is_online):
        self.preload(is_online)
        if self.stimulator:
            print("Graz Begin")
            self.threadStim.start()

    def on_stim(self, stim):
        if stim == "OVTK_StimulationId_ExperimentStop":
            self.destroy_stimulator()
        else:
            param = self.onStimulatorActions.get(stim, None)
            if param:
                self.send_stim(param[0], param[1], 0, param[2])  # 传指令给C# UI
                # print([timestamp, code, 0])

    def destroy_stimulator(self):
        if self.stimulator:
            self.stimulator.stop()
            del self.stimulator
            print('Stimulator Deleted')
        self.send_end()
        self.conn.close()
        self.sock.close()
        print('Graz is closing')

    def send_message(self, data):
        json_bytes = json.dumps(data).encode(encoding="utf-8")
        try:
            self.conn.sendall(bytes((1, 3)))
            self.conn.sendall((len(json_bytes)).to_bytes(4, byteorder='big'))
            self.conn.sendall(json_bytes)
        except socket.error:
            print("connection lost")

    def send_preload(self, visual_resource, auditory_resource):
        self.send_stim(visual_resource, auditory_resource, self.preload_duration, False)

    def send_stim(self, visual_resource, auditory_resource, duration, progress_bar):
        self.send_message({'Type': 'stage', 'VisualResource': visual_resource, 'AuditoryResource': auditory_resource,
                           'Duration': duration, 'ProgressBar': progress_bar})

    def send_score(self, score):
        self.send_progress(score)

    def send_end(self):
        self.send_message({'Type': 'stage', 'End': True})

    def send_progress(self, progress):
        self.send_message({'Type': 'progress', 'Progress': progress})
